home *** CD-ROM | disk | FTP | other *** search
/ Belgian Amiga Club - ADF Collection / BS1 part 65.zip / BS1 part 65 / Delitracker v1.21.adf / Developer / Programming.doc < prev    next >
Text File  |  1992-05-17  |  16KB  |  522 lines

  1.  
  2.  
  3.                 © 1992 by Delirium
  4.                   Date 15.05.1992
  5.  
  6.  
  7.                       How to write an external Player
  8.  
  9.  
  10. DeliTracker supports so called external players. These are players that are in
  11. a special format so that they can be loaded from DeliTracker. If such a player
  12. is loaded, DeliTracker recognises & plays the moduletype that the player
  13. supports. These external players make DeliTracker flexible. New players can be
  14. added by the user and old players can be updated easily. The user can select
  15. only the needed players. The current version DeliTracker can handle up to 64
  16. external players simultaneously. This should be enough for the near future :)
  17.  
  18. When DeliTracker is started it will load all the players in the 'DeliPlayers'
  19. directory (or the specified playerpath e.g. tooltypes or in the configfile).
  20. In addition you can add players while DeliTracker is running.
  21.  
  22. External Players are executables which means they are relocated. At the start
  23. of an external player you can find the characteristic playerstructure. This
  24. structure is generated with four macros. These macros can be found in
  25. 'misc/deliplayer.i'.
  26.  
  27. It is not difficult to adapt a player if you have the replayroutine. You only
  28. need to write some interfacecode. DeliTracker has some helpful builtin
  29. routines that will make this job a lot easier. 
  30.  
  31.  
  32. 1. Basics
  33.  
  34. To adapt a new soundsystem you need the replayroutine of that soundsystem, and
  35. at least 5 modules for testing the adaption.
  36.  
  37.  
  38. 2. Schematics of a external player 
  39.  
  40. {
  41.     Playerheader
  42.  
  43.     TagArray
  44.  
  45.     Interfacecode
  46.  
  47.     Replaycode+Data
  48. }
  49.  
  50.  
  51. 3. Functions that the external players (must) have
  52.  
  53. The PLAYERHEADER macro generates the header that identifies the file as a
  54. valid external player for DeliTracker. This macro must exist and the player
  55. must begin with the macro. The only parameter you must supply is a pointer
  56. to a Tag Array that contains all functions that the external player supports.
  57. In all calls to player functions (except the interrupt routine) a5 will
  58. contain the address to the global player datastructure (Base). For more about
  59. this structure read 'misc/deliplayer.i'. In your routines (except in
  60. DTP_Interrupt) you can trash all registers.
  61.  
  62.  
  63. PLAYERHEADER <tagarray>
  64.  
  65.     tagarray    Pointer to a tag array, terminated with TAG_DONE.
  66.             Tags with ti_Data NULL are ignored.
  67.             Here is a summary of all system tags you may use:
  68.               TAG_DONE
  69.               TAG_IGNORE
  70.               TAG_MORE
  71.               TAG_SKIP
  72.  
  73. DTP_CustomPlayer    this tag identifies a player as customplayer.
  74.             ti_Data may not be NULL !
  75.  
  76. DTP_RequestDTVersion    only if the DeliTracker version is greater than or
  77.             equal to the requested version (ti_Data) will
  78.             DeliTracker accept the player. If your player
  79.             uses functions that were introduced in later revisions
  80.             of DeliTracker you must set this tag according to the
  81.             version that introduced this function.
  82.  
  83. DTP_RequestV37        if this tag is set, only the Kick 2.0 version of
  84.             DeliTracker will accept the player.
  85.             (dtg_GadToolsBase is valid)
  86.  
  87. DTP_PlayerVersion    Tag that contains the revision number of the player.
  88.             If there are two players with same name the player
  89.             with the higher version is used.
  90.  
  91. DTP_PlayerName        ti_Data contains a pointer to the playername. This
  92.             string may be as long as you wish, but only the first
  93.             24 chars are actually used. This tag must exist !
  94.  
  95. DTP_Creator        pointer to the author/adaptor name. This string is
  96.             visible    in the prefs window if the player is selected.
  97.             The string may contain $A as line separator.
  98.  
  99. DTP_Check1        pointer to a module identification routine. This
  100.             routine    is called after the first 1024 bytes of the
  101.             module is loaded. If the module is shorter, the rest
  102.             will contain zero. If the routine recognizes the
  103.             moduleformat it must return d0=0 else d0<>0.
  104.  
  105. DTP_Check2        pointer to a module identification routine. This
  106.             routine    is called after the complete module is loaded
  107.             (and decrunched). If the routine recognizes the module
  108.             it must    return d0=0 else d0<>0.
  109.  
  110. DTP_Extload        pointer to a optional loadroutine for modules. If an
  111.             error occurs d0<>0 else d0=0. Please remember to free
  112.             all allocated resources (memory, locks,...), because
  113.             no further player function is called.
  114.  
  115. DTP_Interrupt        pointer to a interruptroutine. This routine is called
  116.             every 1/50 sec. via a timerinterrupt. Note: your
  117.             interruptroutine is not executed in the    timerinterrupt
  118.             itself. This is the standard method for gaining the
  119.             correct playspeed regardless of the videomode. If the
  120.             DTP_Faster/DTP_Slower pointers are not supplied,
  121.             DeliTracker emulates this by changing the interrupt
  122.             frequency. If this tag doesn't exist, you must
  123.             supply DTP_StartInt/DTP_StopInt.
  124.  
  125. DTP_Stop        pointer to optional stop routine. If this tag is not
  126.             exist, DeliTracker uses the following standard method:
  127.                 stop interrupt (DTP_StopInt)
  128.                 cleanup sound (DTP_EndSnd)
  129.                 reinitialize the song (DTP_InitSnd)
  130.             This routine will stop playing the song, reset the
  131.             'patterncounter' to the begin and change the playspeed
  132.             to default. This means that the interrupt is started
  133.             again and the song should begin to play from the
  134.             beginning.
  135.  
  136. DTP_Config        pointer to an optional initialising routine. This
  137.             routine    is only called once after the player is
  138.             loaded. Purpose:
  139.             The player could load a playerspecific configfile.
  140.  
  141. DTP_Userconfig        pointer to a optional initialising routine. This
  142.             routine is called if the user selects the 'Config'
  143.             button in the prefswindow. Purpose: The player could
  144.             open a playerspecific configwindow for setting
  145.             special options (e.g instrumentpath for a sonix
  146.             player) and saving them into a configfile.
  147.  
  148. DTP_SubSongRange    This tag should be supplied if the player supports
  149.             multimodules. ti_Data points to a function that
  150.             returns in d0 the minimum and in d1 the maximum
  151.             subsong number.
  152.  
  153. DTP_InitPlayer        pointer to an initialising routine, that is called if
  154.             a module is loaded successfully. Must return d0=0 if
  155.             all is ok else d0<>0. The audioallocation must be done
  156.             here. (DeliTracker has a function that does the
  157.             allocation.) If the player supports subsongs it has
  158.             to set dtg_SndNum(a5) to the first subsongnumber.
  159.  
  160. DTP_EndPlayer        pointer to a cleanuproutine, that is called if the
  161.             module is removed from memory. Audiochannels have to
  162.             be freed here. (Use the DeliTracker internal
  163.             supportroutine)
  164.  
  165. DTP_InitSound        pointer to an optional initialising routine. This
  166.             routine    has the task to (re)initialize the module. If
  167.             the interrupt is started the song should begin to play
  168.             at the beginning.
  169.  
  170. DTP_EndSound        pointer to an optional cleanuproutine. For example it
  171.             can be used to reset the volumeregister or the
  172.             audio-dma.
  173.  
  174. DTP_StartInt        pointer to an initialising routine, that must exist if 
  175.             DTP_Interrupt doesn't exist. It has the task to start
  176.             the sound.
  177.  
  178. DTP_StopInt        pointer to a cleanuproutine, that must exist if
  179.             DTP_Interrupt doesn't exist. It has the task to stop
  180.             the sound.
  181.  
  182. DTP_Volume        pointer to function that sets the volume. This
  183.             function is called every time the volume is changed
  184.             (via arexx or slider) and once at the initialising
  185.             phase of the module (before DTP_InitSnd is called).
  186.             The mastervolume can be found in dtg_SndVol(a5). The
  187.             mastervolume is the highest volume allowed. The
  188.             effective volume can be calculated using the
  189.             following formula:
  190.             VOL_eff=((MASTERVOLUME*modulevolume)>>6).
  191.             See also the example sources.
  192.  
  193. DTP_Balance        pointer to a function that sets the balance. This
  194.             function is called every time the balance is changed
  195.             (via arexx or slider) and once at the initialising
  196.             phase of the module (before tf_InitSnd is called).
  197.             The balance for the left channel can be found in
  198.             dtg_SndLBal(a5), for the right channel in
  199.             dtg_SndRBal(a5). Note: All players that support
  200.             balance are capable of volume too! Then you must use
  201.             the same routine for both operations. The mastervolume
  202.             for the left channels can be calculated with this
  203.             formula:
  204.             LeftMaster =((dtg_Volume(a5)*dtg_SndLBal(a5))>>6).
  205.             For the right channels the formula is similar.
  206.  
  207. DTP_Faster        pointer to a function that increases the playspeed.
  208.  
  209. DTP_Slower        pointer to a function that decreases the playspeed.
  210.  
  211. DTP_NextPatt        pointer to a function that increases the
  212.             patternpointer.
  213.  
  214. DTP_PrevPatt        pointer to a function that decreases the
  215.             patternpointer.
  216.  
  217. DTP_NextSong        pointer to a function that increases the
  218.             subsongcounter (only if the subsong exists).
  219.  
  220. DTP_PrevSong        pointer to a function that decreases the
  221.             subsongcounter (only if the subsong exists).
  222.  
  223.  
  224. 4. DeliTracker support functions that can be called from the external player.
  225.  
  226. Every function is called like this:
  227.  
  228.     move.l    dtg_XXX(a5),a0        ; a5 must contain the base
  229.     jsr    (a0)
  230.  
  231. All functions (exept dtg_SongEnd) use d0/d1/a0/a1 as Scratchregister.
  232. A5 must contain the base.
  233.  
  234.  
  235. dtg_GetListData
  236.  
  237.     SYNOPSIS
  238.         memory size = dtg_GetListData(number)
  239.             a0     d0                     d0.l
  240.  
  241.     FUNCTION
  242.         Returns the address and the length of a file that was loaded
  243.         with dtg_LoadFile(). 
  244.  
  245.     INPUTS
  246.         number - number of the file beginning with 0 for the file that
  247.              was selected by the user. 
  248.  
  249.     RESULT
  250.         memory - startaddress of the files in memory, if error NULL.
  251.         size - length of the loaded file in bytes or 0 in case of
  252.                an error
  253.  
  254.  
  255. dtg_LoadFile
  256.  
  257.     SYNOPSIS
  258.         success = dtg_LoadFile(name)
  259.  
  260.     FUNCTION
  261.         Loads and decrunches the specified file to chipmemory.
  262.         Note: this function automatically adds '.pp' to the filename.
  263.  
  264.     INPUTS
  265.         name - store the filename in the internal buffer
  266.                (dtg_PathArray contains a pointer to this buffer)
  267.  
  268.     RESULT
  269.         success - success d0.l=0, else d0.l<>0.
  270.  
  271.  
  272. dtg_CopyDir
  273.  
  274.     SYNOPSIS
  275.         dtg_CopyDir()
  276.  
  277.     FUNCTION
  278.         Copies the directory of the selected file at the end
  279.         of the string, that dtg_PathArray points to.
  280.  
  281.  
  282. dtg_CopyFile
  283.  
  284.     SYNOPSIS
  285.          dtg_CopyFile()
  286.  
  287.     FUNCTION
  288.         Copies the filename of the selected file at the end
  289.         of the string, that dtg_PathArray points to.
  290.  
  291.  
  292. dtg_CopyString
  293.  
  294.     SYNOPSIS
  295.         dtg_CopyString(string)
  296.                                a0
  297.  
  298.     FUNCTION
  299.         a0 contains the address of a string, which is copied at the
  300.         end of the string that dtg_PathArray points to.
  301.  
  302.     INPUTS
  303.         string - a0 contains the pointer to the string
  304.  
  305.  
  306. dtg_AudioAlloc
  307.  
  308.     SYNOPSIS
  309.         success = dtg_AudioAlloc()
  310.  
  311.     FUNCTION
  312.         Allocates the audiochannels
  313.  
  314.     RESULT
  315.         success - if we got them: d0.l=0, else d0.l<>0.
  316.  
  317.  
  318. dtg_AudioFree
  319.  
  320.     SYNOPSIS
  321.         dtg_AudioFree()
  322.  
  323.     FUNCTION
  324.         Frees the audiochannels that were allocated with
  325.         dtg_AudioAlloc.
  326.  
  327.  
  328. dtg_StartInt
  329.  
  330.     SYNOPSIS
  331.         dtg_StartInt()
  332.  
  333.     FUNCTION
  334.         Starts the soundinterrupt. If DTP_Interrupt exists,
  335.         DeliTracker starts the internal timerinterrupt, else
  336.         DTP_StartInt is called.
  337.  
  338.  
  339. dtg_StopInt
  340.  
  341.     SYNOPSIS
  342.         dtg_StopInt()
  343.  
  344.     FUNCTION
  345.         Stops the soundinterrupt. If DTP_Interrupt exists,
  346.         DeliTracker stops the internal timerinterrupt, else
  347.         DTP_StopInt is called.
  348.  
  349.  
  350. dtg_SongEnd
  351.  
  352.     SYNOPSIS
  353.         dtg_SongEnd()
  354.  
  355.     FUNCTION
  356.         Signals DeliTracker, that the module was played once.
  357.         This function doesn't change any registers and is save
  358.         to call from interrupts.
  359.  
  360.  
  361. dtg_CutSuffix
  362.  
  363.     SYNOPSIS
  364.         dtg_CutSuffix()
  365.  
  366.     FUNCTION
  367.         removes the suffix '.pp' at the end of the string, that
  368.         dtg_PathArray points to.
  369.  
  370.  
  371.  
  372. 5. Module-Recognition
  373.  
  374. In order to recognize the different moduleformats every player contains a
  375. specific routine, that tells DeliTracker if the player can play this module or
  376. not. This routine has the task to check certain positions in the module that
  377. are identical in every module (like 'M.K.' at offset $438 in NoiseTracker
  378. modules) or significant assembler instructions (if the module contains the
  379. player). Testing against one or two branches or jumps is NOT enough, cause
  380. many modules with player have branchtables at the beginning of the module. If
  381. the player recognizes the wrong module, a system crash will be the result! So
  382. be careful with the Ckeckroutine. As you can see the playerstructure has two
  383. checkfunctions but the player must use exactly one check routine. This leads
  384. to two basic player types:
  385.  
  386.   1.Type one Player
  387.     Here the Check1 function is implemented.
  388.  
  389.     Advantage: You can implement players that can load the module itself.
  390.     Disadvantage: No Packsupport, more complex.
  391.  
  392.     This type should only be used if you REALLY need to load the module by
  393.     yourself!
  394.     (e.g. FTM, IFF-8SVX player that loads the sample while playing, ...) 
  395.     
  396.  
  397.   2. Type two Player - the easier way 
  398.      Here the Check2 function is implemented.
  399.  
  400.     Advantage: The module may be packed and DeliTracker handles the
  401.            loading and allocation of the module for you.
  402.     Disadvantage: The module is completely loaded into CHIP-Memory.
  403.  
  404. Regardless of the playertype the checkfunction must return d0.l=0 if the
  405. player can handle this module or d0.l<>0 if not.
  406.  
  407. 6. Player-Interrupt
  408.    Players can be divided in two categories:
  409.  
  410.   1. Player that uses the internal timer interrupt from DeliTracker
  411.  
  412.      Advantage: The player is independent from the selected videomode
  413.         The player has automatically the faster/slower function.
  414.         No expense for interrupthandling (interrupt structure
  415.         and the insert/remove code).
  416.         Compatible with the serial.device.
  417.      Disadvantage: The interrupt is not synchronous to the VBlank (This leads
  418.                to problems only to certain cases). 
  419.         
  420.  
  421.   2. Player that generates their own interrupt.
  422.  
  423.      Advantage: You can use other interrupt sources (like AudioIRQ)
  424.         
  425.      Disadvantage: You have to handle the interrupts by yourself, and if
  426.            you use VBlank the player is not independent to the
  427.            videomode.
  428.  
  429.  
  430.     If you use your own timerinterrupt you should allocate CIAB because CIAA
  431.     is used from the system under 2.x. It is wise not to run the soundcode
  432.     directly in the timerinterrupt. Instead you should Cause() a SoftInt in
  433.     the timer interrupt and execute the routine in the SoftInt. This is to
  434.     assure maximum compatibility for modem users because the SoftInt has a
  435.     lower priority thant the RBF interrupt. Beware of writing directly to the
  436.     680x0 intvectors! You should use AddIntServer() or SetIntVector() from
  437.     the OS.
  438.  
  439.  
  440. 7. Custom Modules
  441.    These are not modules in the conventional meaning. They are more like
  442.    external players, the difference is that custom modules contain the 
  443.    player AND the module. With the custom module interface you can adapt
  444.    almost every module. If you have more modules with the same replay 
  445.    routine we suggest to write an own player for this moduleformat. 
  446.  
  447.  
  448. Schematic of a custom module (custom player)
  449.  
  450. {
  451.     Playerheader
  452.  
  453.     TagArray
  454.  
  455.     Interfacecode
  456.  
  457.     Replaycode+Data
  458.     
  459.     MODULE
  460. }
  461.  
  462. The Tag DTP_CustomPlayer identifies a player as a custom module.
  463. The following Tags are ignored for custommodules:
  464.  
  465.     - DTP_PlayerVersion
  466.      - DTP_PlayerName
  467.     - DTP_Creator
  468.     - DTP_Check1
  469.     - DTP_Check2
  470.     - DTP_ExtLoad
  471.     - DTP_Config
  472.     - DTP_UserConfig
  473.  
  474.  
  475. 8. Checklist
  476. This is a small list that you should match when you create your own player or
  477. custom module.
  478.  
  479.     [ ] checkroutine exact enough ?
  480.     [ ] audiochannel allocated/freed correctly ?
  481.     [ ] all allocated memory freed after playing?
  482.     [ ] all locks unlocked after playing ?
  483.     [ ] enforcer and mungwall proof ?
  484.     [ ] viable error handling path taken for ALL possible errors ?
  485.     [ ] player tested under 1.3 and 2.0 ?
  486.     [ ] does the player work correct in all videomodes ?
  487.  
  488.  
  489. 9. Other things
  490.  
  491. The player should not change the LED condition because DeliTracker will handle
  492. it.
  493.  
  494. Problems
  495.  
  496. Symptom        possible source                elimination
  497.  
  498. crash        a5 trashed, other registers
  499.         not saved, wrong stack usage
  500.         initialization wrong or too late 
  501.         module too new for the replayroutine    better check
  502.  
  503. module sounds    Audio data not in chipmem
  504. wrong        wrong initialization
  505.         module too new for the replayroutine
  506.         player needs some special values
  507.         in some registers            extra init code
  508.         wrong videomode
  509.  
  510. no sound    Audio-DMA off                :-)
  511.   >68000    player writes directly to processor    use OS routines to
  512.         intvectors and VBR is not 0.        set IntVectors
  513.  
  514. no free        wrong interrupt handling        VBlank-IRQ:
  515. CPU-time                        Z-Flag must be set
  516.                             at the end of the 
  517.                             interruptroutine. 
  518.  
  519. slow system    68000/020/030 toooo slow        buy a 68040 or
  520.                             CRAY ;-)
  521.  
  522.